﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharedLib.MessageFramework;
using Tracy.DataModel;
using SharedLib.MessageFramework.Messages;
using System.Xml;
using System.Collections.ObjectModel;
using Tracy.BasicServices;
using SharedLib;
using Microsoft.Practices.Unity;
using SharedLib.MessageFramework.Handlers;
using Tracy.DataModel.SourceParser;

namespace Tracy.Handlers
{
    public class FeedScanHandler : TaskMessageHandler
    {
        public static event EventHandler<GenericEventArgs<List<Resource>>> ResourcesFound;
        private object _lockHelperGeneralProcess = new object();
        private object _lockHelperResultHandling = new object();
        //The mapping for URL, FeedSources and Entries
        //TODO: convert to static?
        private IDictionary<string, IDictionary<FeedSource, ICollection<Entry>>> _processingURLMapping = new Dictionary<string, IDictionary<FeedSource, ICollection<Entry>>>();

        private IDictionary<string, IDictionary<FeedSource, ICollection<Entry>>> ProcessingURLMapping
        {
            get {
                return _processingURLMapping;
            }
        }
        private IDictionary<FeedSource, ISourceParser> _sourceParserCache = new Dictionary<FeedSource, ISourceParser>();

        private IDictionary<FeedSource, ISourceParser> SourceParserCache
        {
            get {

                return _sourceParserCache; 
            }
        }

        public FeedScanHandler()
        {

        }

        TaskMessage _currentMsg;
        protected override void ProcessMessage(TaskMessage msg)
        {
            lock (_lockHelperGeneralProcess)
            {
                _currentMsg = msg;
                base.ProcessMessage(msg);
                foreach (FeedSource source in TracyFacade.Instance.FilterManager.FeedSourceProvider.GetItems)
                {
                    ISourceParser parser = GetSourceParser(source);
                    if (parser != null)
                    {
                        List<Entry> entriesToScan = null;
                        if (msg.Data != null) 
                        {
                            if (msg.Data is Entry)
                            {
                                //May scan on single entry
                                entriesToScan = new List<Entry>();
                                entriesToScan.Add((Entry)msg.Data);
                            }
                            else if (msg.Data is List<Entry>)
                            {
                                //Scan multi entries
                                entriesToScan = (List<Entry>) msg.Data;
                            }
                        }

                        if(entriesToScan == null)
                        {
                            //Scan all entries by default
                            entriesToScan = TracyFacade.Instance.EntryProvider.GetItems();
                        }

                        foreach (Entry entry in entriesToScan)
                        {
                            if (!entry.TracingDisabled)
                            {
                                foreach (FilterSet filterSet in TracyFacade.Instance.FilterManager.FilterProvider.GetFilterSets(entry))
                                {
                                    if (filterSet.FeedSource.Name == source.Name)//Skip sources that not found in filtersets
                                    {
                                        parser.Parse(source, entry);
                                        break;
                                    }
                                }
                            }
                        }

                    }
                }
            }

        }

        private static List<Resource> ProcessRetrievedResources(IList<Resource> result)
        {
            List<Resource> newItemsFound = new List<Resource>();
            List<string> resTitles = new List<string>();
            //Handle filtered resources
            foreach (Resource res in result)
            {
                if (!resTitles.Contains(res.Title) && !TracyFacade.Instance.ResourceProvider.IsResourceExisting(res))
                {
                    resTitles.Add(res.Title);
                    //TracyBus.Instance.ResourceProvider.AddItem(res);
                    newItemsFound.Add(res);
                }
            }
            return newItemsFound;
        }

        void Parser_OnResultFound(object sender, GenericEventArgs<SourceParserResult> e)
        {
            lock (_lockHelperResultHandling)
            {
                if (e != null && e.Data != null)
                {
                    List<Resource> result = ResourceFilter.FilterRawResources(e.Data.ResultDoc, e.Data.Entry, e.Data.Source);
                    List<Resource> newItemsFound = ProcessRetrievedResources(result);
                    //Notify UI
                    if (newItemsFound.Count > 0)
                        ResourcesFound.InvokeEvent(this, new GenericEventArgs<List<Resource>>(newItemsFound));
                        //TracyFacade.Instance.MessageDispatcher.NotifyUI(_currentMsg, NotifyUIEventArgs.FOUND_RESOURCE, newItemsFound);
                }
            }
        }

        private ISourceParser GetSourceParser(FeedSource source)
        {
            ISourceParser parser;
            if (!SourceParserCache.ContainsKey(source))
            {
                parser = TracyFacade.Instance.DIContainer.Resolve<ISourceParser>(source.Parser);//Defined in Sources.xml
                SourceParserCache.Add(source, parser);
                parser.OnResultFound += new EventHandler<GenericEventArgs<SourceParserResult>>(Parser_OnResultFound);
            }
            else
            {
                parser = SourceParserCache[source];
            }
            return parser;
        }
    }
}
